package com.carlinfo.common.dao.impl;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import com.carlinfo.common.dao.IBaseDao;
import com.carlinfo.common.util.DbUtil;
import com.carlinfo.common.util.PageInfoUtil;

public abstract class BaseDaoImpl<T> implements IBaseDao<T>
{
	protected Object pojoObj;
	protected Logger logger = LogManager.getLogger();

	/**
	 * 
	 * @param sql        要执行的SQL语句 有占位符
	 * @param paramsList 占位符所对应的值
	 * @return
	 */
	protected T findOneJDBC(String sql, List<Object> paramsList)
	{
		DbUtil dbutil = DbUtil.getInstance();
		Connection conn = dbutil.getconn();
		PreparedStatement pre = null;
		ResultSet res = null;
		try
		{
			pre = conn.prepareStatement(sql);
			int count = 1;
			for (Iterator iterator = paramsList.iterator(); iterator.hasNext();)
			{
				Object val = (Object) iterator.next();
				pre.setObject(count, val);
				count++;
			}
			res = pre.executeQuery();
//			logger.info("sql:{},paramList:{}", sql, paramsList);
			if (res.next())
			{
				T T = converFromDb(res);
				return T;
			}
		} catch (SQLException e)
		{
			e.printStackTrace();
		} finally
		{
			dbutil.closeAll(conn, pre, res);
		}
		return null;
	}

	/**
	 * 
	 * @param pageInfoUtil 分页对象
	 * @param sql          SQL语句 只有SQL语句和占位符
	 * @param paramsList   占位符所对应的值
	 * @return
	 */
	protected List<T> findListByPage(PageInfoUtil pageInfoUtil, String sql, List<Object> paramsList)
	{
		List<T> resultList = new ArrayList<T>();
		DbUtil dbutil = DbUtil.getInstance();
		Connection conn = dbutil.getconn();
		PreparedStatement pre = null;
		ResultSet res = null;
		try
		{
			int count = 1;
			if (pageInfoUtil != null)
			{/**
				 * 获取数据的总条数
				 */
				int indexOf = sql.indexOf("from");
				String countSql = "select count(*) " + sql.substring(indexOf, sql.length());
				pre = conn.prepareStatement(countSql);

				count = 1;
				for (Iterator iterator = paramsList.iterator(); iterator.hasNext();)
				{
					Object val = (Object) iterator.next();
					pre.setObject(count, val);
					count++;
				}
				res = pre.executeQuery();
				if (res.next())
				{
					int totalRecord = res.getInt(1);
					pageInfoUtil.setTotalRecord(totalRecord);
				}
				res.close();
				pre.close();

				sql = sql + " limit ?,? ";
				paramsList.add(pageInfoUtil.getCurrentRecord());
				paramsList.add(pageInfoUtil.getPageSize());
			}
			pre = conn.prepareStatement(sql);
			count = 1;
			for (Iterator iterator = paramsList.iterator(); iterator.hasNext();)
			{
				Object val = (Object) iterator.next();
				pre.setObject(count, val);
				count++;
			}
			res = pre.executeQuery();
			while (res.next())
			{
				T t = converFromDb(res);
				/* 放到集合中 */
				resultList.add(t);
			}
			return resultList;
		} catch (SQLException e)
		{
			e.printStackTrace();
		} finally
		{
			dbutil.closeAll(conn, pre, res);
		}
		return Collections.emptyList();
	}

	/**
	 * 
	 * @param sql        要执行的SQL语句，包含占位符
	 * @param paramsList 为占位符赋值
	 * @return
	 */
	protected List<T> findList(String sql, List<Object> paramsList)
	{
		List<T> resultList = new ArrayList<T>();
		DbUtil dbutil = DbUtil.getInstance();
		Connection conn = dbutil.getconn();
		PreparedStatement pre = null;
		ResultSet res = null;
		try
		{
			pre = conn.prepareStatement(sql);
			int count = 1;
			for (Iterator iterator = paramsList.iterator(); iterator.hasNext();)
			{
				Object val = (Object) iterator.next();
				pre.setObject(count, val);
				count++;
			}
			res = pre.executeQuery();
			while (res.next())
			{
				T t = converFromDb(res);
				/* 放到集合中 */
				resultList.add(t);
			}
			return resultList;
		} catch (SQLException e)
		{
			e.printStackTrace();
		} finally
		{
			dbutil.closeAll(conn, pre, res);
		}
		return Collections.emptyList();
	}

	/**
	 * 
	 * @param sql        要执行的SQL语句 有占位符
	 * @param paramsList 为占位符赋值的List
	 * @return
	 */
	protected int executeJDBC(String sql, List<Object> paramsList)
	{
		DbUtil dbutil = DbUtil.getInstance();
		Connection conn = dbutil.getconn();
		PreparedStatement pre = null;
		ResultSet res = null;
		try
		{
			pre = conn.prepareStatement(sql);
			int count = 1;
			for (Iterator<Object> iterator = paramsList.iterator(); iterator.hasNext();)
			{
				Object val = (Object) iterator.next();
				pre.setObject(count, val);
				count++;
			}
			int re = pre.executeUpdate();
			if (re > 0)
			{
				return re;
			} else
			{
				return 0;
			}
		} catch (SQLException e)
		{
			e.printStackTrace();
		} finally
		{
			dbutil.closeAll(conn, pre, res);
		}
		return 0;
	}

	/**
	 * 
	 * @param sql
	 * @param paramsList
	 * @param condMap
	 * @return
	 */
	protected int executeJDBC(String sql, List<Object> paramsList, Map<String, Object> resultMap)
	{
		DbUtil dbutil = DbUtil.getInstance();
		Connection conn = dbutil.getconn();
		PreparedStatement pre = null;
		ResultSet res = null;
		try
		{
			pre = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
			int count = 1;
			for (Iterator iterator = paramsList.iterator(); iterator.hasNext();)
			{
				Object val = (Object) iterator.next();
				pre.setObject(count, val);
				count++;
			}
			int rs = pre.executeUpdate();
			res = pre.getGeneratedKeys();
			if (res.next())
			{
				int id = res.getInt(1);
				resultMap.put("id", id);
			}
			return rs;
		} catch (SQLException e)
		{
			e.printStackTrace();
		} finally
		{
			dbutil.closeAll(conn, pre, res);
		}
		return 0;
	}

	protected T converFromDb(ResultSet rs) 
			throws SQLException
	{
		try
		{
			/*----列出pojo中所有的属性----*/
			/* 获取Class对象
			 * 改包名咋办
			 *  */
			/*Class.forName("com.carlinfo.demo.pojo.ADynasty")*/
			Class cla = pojoObj.getClass();
			/* new对象 */
			T valObj = (T) cla.newInstance() ; 
			/* 列出所有的属性 */
			Field[] allFields = cla.getDeclaredFields();
			for (int i = 0; i < allFields.length; i++)
			{
				Field field = allFields[i];
				try
				{
					//this.logger.info("--i:{}--所有的属性:{}--name:{}===>",i,field,field.getName());
					/* 属性的名字,和表的列名一样 */
					String fileName = field.getName() ; 
					
//					this.logger.info("--{}--{}--{}--",i,field.getName());
					if("byte".equalsIgnoreCase(field.getType().getName())||
						"int".equalsIgnoreCase(field.getType().getName())||
						"double".equalsIgnoreCase(field.getType().getName())||
						String.class.getName().equalsIgnoreCase(field.getType().getName())||
						Date.class.getName().equalsIgnoreCase(field.getType().getName())) 
					{
						//接着往下执行
						if(fileName.toLowerCase().endsWith("str")) 
						{
							continue ;
						}
					}else 
					{
						//跳过本次的循环，进行下次的循环
						continue;
					}
					/* 获取数据库的值
					 * 整数:是第几列
					 * 字符串:列的别名
					 *  */
					Object val = rs.getObject(fileName);
					/* 将此值设置到对象中
					 * fileName:属性名
					 * 读写器:写:set属性名(属性名的首字母大写)
					 *  */
					String setName = "set" + fileName.substring(0, 1).toUpperCase() 
							+ fileName.substring(1, fileName.length()); 
					/*
					 * setMethod获取到方法对象
					 * 参数1:方法名
					 * 参数2:形参
					 * 方法定义 
					 * */
					Method setMethod = cla.getMethod(setName, field.getType());
					//this.logger.info("==name:{},val:{}===setName:{};class:{}",
					//		field.getName(),val,setName,field.getType());
					/* 处理各别的类型 */
					if("byte".equalsIgnoreCase(field.getType().getName()))
					{
						/* 说明是Byte类型 */
						setMethod.invoke(valObj, Byte.valueOf(val + ""));
					}else if("double".equalsIgnoreCase(field.getType().getName()))
					{
						/* 说明是Byte类型 */
						setMethod.invoke(valObj, Double.valueOf(val + ""));
					}else
					{
						/* 调用方法
						 * 参数1:对象
						 * 参数2:实参;是从数据库中取出来的
						 * 返回值:方法的返回值;set方法有返回值吗?;
						 *  */
						setMethod.invoke(valObj, val);
					}
				}catch(Exception e)
				{
					this.logger.error("赋值失败;",e);
				}
			}
			
			return valObj; 
		} catch (Exception e)
		{
			this.logger.error("从数据库中赋值给对象失败了;",e);
		}
		return null ; 
	}
}
